package net.ankao.job.job;

import lombok.extern.slf4j.Slf4j;
import net.ankao.job.common.ClientJobResult;
import net.ankao.job.common.Constant;
import net.ankao.job.common.HeartbeatNamingManager;
import net.ankao.job.common.JobNamingManager;
import net.ankao.job.core.common.JobRequest;
import net.ankao.job.core.rpc.IAkJobClientService;
import net.ankao.job.entity.AkApplicationClient;
import net.ankao.job.entity.AkApplicationJob;
import net.ankao.job.entity.AkJobTask;
import net.ankao.job.service.IAkApplicationClientService;
import net.ankao.job.service.IAkJobTaskService;
import org.quartz.*;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author LILU
 * @date 2024-11-28 11:08
 */
@Slf4j
@Component
public class ClientJob implements Job, ApplicationContextAware {

    private static ApplicationContext staticApplicationContext;

    public IAkApplicationClientService getAkApplicationClientService() {
        return staticApplicationContext.getBean(IAkApplicationClientService.class);
    }

    public IAkJobTaskService getAkJobTaskService() {
        return staticApplicationContext.getBean(IAkJobTaskService.class);
    }

    public HeartbeatNamingManager getHeartbeatNamingManager() {
        return staticApplicationContext.getBean(HeartbeatNamingManager.class);
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail jobDetail = context.getJobDetail();
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        AkApplicationJob applicationJob = (AkApplicationJob) jobDataMap.get(Constant.APPLICATION_JOB_KEY);
        Map<String, Object> wrappedMap = jobDataMap.getWrappedMap();
        HashMap<String, String> params = new HashMap<>();
        wrappedMap.forEach((k, v) -> {
            if (Constant.APPLICATION_JOB_KEY.equals(k)) {
                return;
            }
            params.put(k, v != null ? v.toString() : null);
        });
        doTask(applicationJob,params,"自动执行");
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        staticApplicationContext = applicationContext;
    }

    /**
     * 执行远程调用任务
     * @param applicationJob
     * @param params
     */
    public void doTask(AkApplicationJob applicationJob,HashMap<String, String> params,String remark){
        List<AkApplicationClient> byExecutiveStrategy = getAkApplicationClientService().getByExecutiveStrategy(applicationJob);
        if(byExecutiveStrategy.isEmpty()){
            AkJobTask akJobTask = getAkJobTaskService().init(null, applicationJob, params, remark);
            getAkJobTaskService().updateResult(akJobTask.getId(), 0, "无可用节点");
            return;
        }
        byExecutiveStrategy.parallelStream().forEach(applicationClient -> {
            AkJobTask akJobTask = getAkJobTaskService().init(applicationClient, applicationJob, params, remark);
            if (applicationClient == null) {
                // 无可用节点
                getAkJobTaskService().updateResult(akJobTask.getId(), 0, "无可用节点");
                return;
            }
            IAkJobClientService naming = getHeartbeatNamingManager().getNaming(applicationClient.getId());
            if (naming == null) {
                // 无可用节点
                getAkJobTaskService().updateResult(akJobTask.getId(), 0, "无可用节点");
                return;
            }
            JobRequest jobRequest = new JobRequest();
            jobRequest.setJobName(applicationJob.getBeanName());
            jobRequest.setTaskId(akJobTask.getId());
            jobRequest.setTimeOut(applicationJob.getTimeOut());
            jobRequest.setParams(params);
            try {
                naming.doTask(jobRequest);
            } catch (RemoteException e) {
                getAkJobTaskService().updateResult(akJobTask.getId(), 0, e.getMessage());
                //TODO 开始重试
                if (applicationJob.getRetryNum() != null && applicationJob.getRetryNum() > 0) {

                }
            }
        });
    }
}
